package com.forever7776.life.core.service.qiniu;

import com.alibaba.fastjson.JSONObject;
import com.forever7776.life.core.common.enums.QiNiuEnum;
import com.forever7776.life.core.constants.SystemConstant;
import com.forever7776.life.core.entity.sys.SysFile;
import com.forever7776.life.core.service.sys.ISysFileService;
import com.qiniu.common.QiniuException;
import enums.ResultEnum;
import org.apache.commons.codec.net.URLCodec;
import org.apache.commons.lang3.StringUtils;
import org.apache.tomcat.util.http.fileupload.disk.DiskFileItem;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.commons.CommonsMultipartFile;
import qiniu.QiNiuApi;
import util.ConfigTool;
import util.DateUtil;
import util.FileUtil;
import util.ResultUtil;

import java.awt.*;
import java.awt.image.BufferedImage;
import java.awt.image.CropImageFilter;
import java.awt.image.FilteredImageSource;
import java.awt.image.ImageFilter;
import java.io.File;
import java.io.IOException;
import java.util.Date;

/**
 * 七牛上传辅助类
 *
 * @author kz
 */
@Service
public class QiNiuService {
    private static Logger logger = LoggerFactory.getLogger(QiNiuService.class);
    private static String domain = StringUtils.EMPTY;

    /**
     * 图片超过2MB加上廋身参数
     */
    private static final long NEED_IMAGE_SLIM = 1024 * 1024 * 2;

    private static final String IMAGE_SLIM_NAME = "?imageslim";
    @Autowired
    private ISysFileService sysFileService;

    public static String url(String filename) {
        try {
            if (StringUtils.isBlank(domain)) {
                domain = ConfigTool.getProp("qiniu.domain");
            }
            return "http://" + domain + "/" + new URLCodec("UTF-8").encode(filename).replace("+", "%20");
        } catch (Exception e) {
            logger.error("QiNiuService@url error", e);
            return StringUtils.EMPTY;
        }
    }

    public void run(File file, SysFile sysFile) {
        Thread upThread = new Thread(new UploadProcess(file, sysFile));
        upThread.start();
        logger.info("QiNiu file-Thread[" + upThread.getId() + "] begin on");
    }

    public boolean upload(MultipartFile multipartFile) {
        try {
            long begin = System.currentTimeMillis();
            String originFileName = multipartFile.getOriginalFilename();
            CommonsMultipartFile cf = (CommonsMultipartFile) multipartFile;
            DiskFileItem fi = (DiskFileItem) cf.getFileItem();
            File file = fi.getStoreLocation();
            JSONObject jo = QiNiuApi.upload(file);
            save(jo, new SysFile());
            logger.info("本次上传耗时：{}ms,文件名：{}，上传完毕时间：{}", (System.currentTimeMillis() - begin), originFileName, DateUtil.format(new Date(), DateUtil.YYYY_MM_DD_HH_MM_SS));
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("uploadProcess@QiNiuUpload save model error", e);
        }

        return false;
    }

    public boolean upload(File file, SysFile sysFile) {
        try {
            JSONObject jo = QiNiuApi.upload(file);
            save(jo, sysFile);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("uploadProcess@QiNiuUpload save model error", e);
        }

        return false;
    }

    public JSONObject uploadFileByte(byte[] fileByte, String fileKey, SysFile sysFile) {
        JSONObject result = ResultUtil.getSuccessResult("上传成功");
        try {
            result = QiNiuApi.uploadFileByte(fileByte, fileKey);
            save(result, sysFile);
            return result;
        } catch (Exception e) {
            result.put("code", ResultEnum.STATUS.FAIL.getCode());
            logger.error("uploadProcess@QiNiuUpload save model error", e);
        }

        return result;
    }

    public void save(JSONObject jo, SysFile sysFile) {
        if ("success".equals(jo.getString("result_code"))) {
            String key = jo.getString("key");
            sysFile.setFileStatus(QiNiuEnum.STATUS.SUCCESS.getKey());
            sysFile.setFileSuffix(FileUtil.getFileSuffix(key));
            sysFile.setInsertDate(new Date());
            logger.info("[upload]上传结果返回-->key:" + key);
        } else {
            logger.info("[upload]上传失败");
            sysFile.setFileStatus(QiNiuEnum.STATUS.FAIL.getKey());
        }
        if (sysFileService != null) {
            sysFileService.insert(sysFile);
        }

    }

    class UploadProcess implements Runnable {
        private File file;
        private SysFile sysFile;

        public UploadProcess(File file, SysFile sysFile) {
            this.file = file;
            this.sysFile = sysFile;
        }

        @Override
        public void run() {
            upload(file, sysFile);
        }
    }


    /**
     * 移动文件，要求空间在同一账号下
     *
     * @param fromBucket  源空间名称
     * @param fromFileKey 源文件名称
     * @param toBucket    目的空间名称
     * @param toFileKey   目的文件名称
     * @param force       强制覆盖空间中已有同名（和 toFileKey 相同）的文件
     * @throws QiniuException
     */
    public void moveFile(String fromBucket, String fromFileKey, String toBucket, String toFileKey, boolean force) throws QiniuException {
        QiNiuApi.moveFile(fromBucket, fromFileKey, toBucket, toFileKey, force);
    }

    /**
     * 删除指定空间、文件名的文件
     *
     * @param bucket 空间名称
     * @param key    文件名称
     * @throws QiniuException
     * @link http://developer.qiniu.com/kodo/api/delete
     */
    public void delete(String bucket, String key) throws QiniuException {
        QiNiuApi.delete(bucket, key);
    }

    public JSONObject pic(MultipartFile multipartFile, String userId) throws IOException {
        long begin = System.currentTimeMillis();
        JSONObject result = new JSONObject();
        if (multipartFile.isEmpty()) {
            result.put("msg", "图片为空");
            result.put("success", false);
            return result;
        }
        String originFileName = multipartFile.getOriginalFilename();
        if (!StringUtils.contains(SystemConstant.QINIU_SUFFIXIMAGE, FileUtil.getFileSuffix(originFileName).toUpperCase())) {
            result.put("msg", "图片类型不对");
            result.put("success", false);
            return result;
        }
        long fileSize = multipartFile.getSize();
        String newFileName = userId + SystemConstant.QINIU_SLASH + originFileName;
        SysFile sysFile = new SysFile();
        sysFile.setUserId(userId);
        sysFile.setFileType(0);
        sysFile.setFileName(originFileName);
        sysFile.setFileSize(fileSize);
        if (fileSize > NEED_IMAGE_SLIM) {
            sysFile.setFileKey(originFileName + IMAGE_SLIM_NAME);
        }
        try {
            result = uploadFileByte(multipartFile.getBytes(), newFileName, sysFile);
        } catch (QiniuException q) {
            new QiNiuApi(ConfigTool.getProp("qiniu.access"), ConfigTool.getProp("qiniu.secret"), ConfigTool.getProp("qiniu.bucket"));
            logger.info("##########七牛重新连接成功##########");
            result = uploadFileByte(multipartFile.getBytes(), newFileName, sysFile);
        }

        logger.info("本次上传耗时：{}ms,文件名：{}，上传完毕时间：{}", (System.currentTimeMillis() - begin), originFileName, DateUtil.format(new Date(), DateUtil.YYYY_MM_DD_HH_MM_SS));
        return result;
    }


    /**
     * 切图
     *
     * @param src
     * @param x
     * @param y
     * @param w
     * @param h
     * @return
     */
    public BufferedImage cropImg(BufferedImage src, int x, int y, int w, int h) {
        ImageFilter cropFilter = new CropImageFilter(x, y, w, h);
        Image img = Toolkit.getDefaultToolkit().createImage(new FilteredImageSource(src.getSource(), cropFilter));
        BufferedImage newImg = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
        Graphics g = newImg.getGraphics();
        g.drawImage(img, 0, 0, null);
        g.dispose();
        return newImg;
    }

    /**
     * 获取图片名称
     *
     * @param url
     * @return
     */
    public String getImageName(String url) {
        int lastindex = url.lastIndexOf("/");
        String imgName = url.substring(lastindex + 1);
        return imgName;

    }

    /**
     * 获取图片类型
     *
     * @param url
     * @return
     */
    public String getImageType(String url) {
        int lastindex = url.lastIndexOf("/");
        String imgName = url.substring(lastindex + 1);
        int pointIndex = imgName.indexOf(".");
        return imgName.substring(pointIndex + 1);
    }

}
